package com.wave.wavesystem.serve.controller;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryWrapper;
import com.wave.common.enums.ErrorCode;
import com.wave.common.model.DeleteRequest;
import com.wave.common.model.Result;
import com.wave.common.util.Func;
import com.wave.wavesystem.serve.pojo.entity.Menu;
import com.wave.wavesystem.serve.pojo.query.MenuQuery;
import com.wave.wavesystem.serve.pojo.vo.menu.MenuVO;
import com.wave.wavesystem.serve.service.IMenuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;


@RestController
@RequestMapping("/menu")
@RequiredArgsConstructor
@Tag(name = "菜单接口-MenuController")
public class MenuController {

    private final IMenuService service;

    @PostMapping("/save")
    @Operation(summary = "新增")
    public Result<Menu> save(@RequestBody Menu entity) {
        service.save(entity);
        return Result.success(entity);
    }

    @PostMapping("/delete")
    @Operation(summary = "通过 ids 删除")
    public Result<Void> delete(@RequestBody DeleteRequest deleteRequest) {
        if (Func.isEmpty(deleteRequest.getIds())) {
            return Result.fail(ErrorCode.NEED_PARAMS);
        }
        List<Long> removeIds = Func.strToLongList(deleteRequest.getIds());
        List<Long> longs = reCheck(removeIds, new ArrayList<>());
        service.removeByIds(longs);
        return Result.success();
    }

    private List<Long> reCheck(List<Long> ids, List<Long> all) {
        all.addAll(ids);
        List<Menu> list = service.queryChain().in(Menu::getParentId, ids).list();
        if (Func.isEmpty(list)) {
            return all;
        }
        List<Long> list1 = list.stream().map(Menu::getId).toList();
        reCheck(list1, all);
        return all;
    }

    @PostMapping("/modify")
    @Operation(summary = "修改")
    public Result<Menu> modify(@RequestBody Menu entity) {
        service.updateById(entity);
        return Result.success(entity);
    }

    @PostMapping("/query")
    @Operation(summary = "根据条件查询")
    public Result<Menu> query(@RequestBody MenuQuery query) {
        Menu entity = service.getById(query.getId());
        return Result.success(entity);
    }

    @PostMapping("/list")
    @Operation(summary = "列表")
    public Result<List<Menu>> list(@RequestBody MenuQuery query) {
        QueryChain<Menu> queryChain = service.getQueryChain(query);
        List<Menu> list = service.list(queryChain);
        return Result.success(list);
    }

    @PostMapping("/page")
    @Operation(summary = "分页")
    public Result<Page<MenuVO>> page(@RequestBody MenuQuery query) {
        QueryChain<Menu> queryChain = service.getQueryChain(query);
        Page<Menu> page = service.page(new Page<>(query.getPageNum(), query.getPageSize()), queryChain);
        Page<MenuVO> MenuVOPage = new Page<>();
        BeanUtils.copyProperties(page, MenuVOPage);
        if (Func.isNotEmpty(page.getRecords())) {
            List<MenuVO> MenuVOS = page.getRecords().stream().map(Menu -> {
                MenuVO MenuVO = new MenuVO();
                BeanUtils.copyProperties(Menu, MenuVO);
                return MenuVO;
            }).toList();
            MenuVOPage.setRecords(MenuVOS);
        }
        return Result.success(MenuVOPage);
    }

    @PostMapping("/tree")
    @Operation(summary = "菜单树形结构")
    public Result<List<Menu>> tree() {
        QueryWrapper qw = QueryWrapper.create();
        qw.isNull(Menu::getParentId);
        List<Menu> menus = service.getMapper().selectListWithRelationsByQuery(qw);
        if (Func.isNotEmpty(menus)) {
            handelMenuSort(menus);
        }
        return Result.success(menus);
    }

    private void handelMenuSort(List<Menu> menus) {
        if (Func.isNotEmpty(menus)) {
            menus.sort(Comparator.comparing(Menu::getSort));
        }
        menus.forEach(item -> {
            if (Func.isNotEmpty(item.getChildren())) {
                handelMenuSort(item.getChildren());
            }
        });
    }

}
